import { diskStorage } from 'multer';
import { mkdirSync } from 'node:fs';
import { extname, join, parse } from 'node:path';
import * as sharp from 'sharp';
import { Response } from 'express';
import { InjectConnection } from '@nestjs/mongoose';
import { version as appVersion } from '../../package.json';

import {
  Controller,
  Get,
  Inject,
  LoggerService,
  Param,
  Post,
  Res,
  UploadedFiles,
  UseInterceptors,
} from '@nestjs/common';
import { Connection } from 'mongoose';
import { FileFieldsInterceptor } from '@nestjs/platform-express';
import configuration from '@/config/configuration';
import { ValidationException } from '@/common/exceptions/custom-exception';
import { Public } from '@/auth/decorators/public.decorator';
import { UtilService } from './utils.servece';
import { RedisService } from '@/common/redis/redis.service';

@Controller()
export class UtilController {
  constructor(
    private readonly utilServece: UtilService,
    private readonly redisService: RedisService,
    @InjectConnection() private readonly mongodbConnection: Connection,
    @Inject('CustomLogger') private readonly logger: LoggerService,
  ) {}

  @Post('utils/upload-img')
  @UseInterceptors(
    FileFieldsInterceptor([{ name: 'file', maxCount: 1 }], {
      storage: diskStorage({
        destination(req, file, callback) {
          const tmpdir = configuration().upload.dest;
          mkdirSync(tmpdir, { recursive: true });
          callback(null, tmpdir);
        },
        filename(req, file, callback) {
          const uniqueSuffix = Date.now();
          const ext = extname(file.originalname);
          callback(null, `${uniqueSuffix}${ext}`);
        },
      }),
    }),
  )
  async uploadImg(
    @UploadedFiles()
    files: {
      file?: Express.Multer.File[];
    },
  ) {
    const file = files.file[0];
    if (!file) {
      throw new ValidationException('uploadFileFail');
    }
    const imageSource = sharp(file.path);
    const tmpdir = configuration().upload.dest;

    const metaData = await imageSource.metadata();
    let thumbnailName;
    if (metaData.width > 300) {
      const { name, ext } = parse(file.filename);
      thumbnailName = `${name}_thumbnail${ext}`;
      imageSource.resize(300).toFile(join(tmpdir, thumbnailName));
    }
    const publicDir = configuration().upload.public;
    const publicUrl = configuration().publicUrl;
    const url = `${publicUrl}/${publicDir}/${file.filename}`;
    const thumbnailUrl = `${publicUrl}/${publicDir}/${thumbnailName ? thumbnailName : file.filename}`;
    return { url, thumbnailUrl };
  }

  @Public()
  @Get('/pages/:uuid')
  async renderH5Page(
    @Res() res: Response,
    // @Param('id') id: string,
    @Param('uuid') uuid: string,
  ) {
    const pageData = await this.utilServece.renderToPageData({
      uuid,
    });
    res.render('page.nj', pageData);
  }

  @Public()
  @Get('/ping')
  async index() {
    // 获取redis版本
    const info = await this.mongodbConnection.db.admin().serverInfo();
    const redisInfo = (await this.redisService.info()).match(
      /redis_version:(\d+\.\d+\.\d+)/,
    )[1];
    return { mongo: info.version, redis: redisInfo, appVersion: appVersion };
  }
}
